package com.demo.test;

import java.util.ArrayList;
import java.util.List;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.context.ContextUtil;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.degrade.circuitbreaker.EventObserverRegistry;

public class Demo2 {

	public static void main(String[] args) throws BlockException {
		String resourceName = "nodeA";
		initDegradeRule(resourceName);

		// 创建一个名称为entrance1，来源为appA 的上下文Context，同一个线程里不管执行多少次，返回的都是第一次创建的context
		ContextUtil.enter("entrance1", "appA");

		// 添加状态变化监听器
		// name没有业务含义，用来删除监听器
		EventObserverRegistry.getInstance().addStateChangeObserver("xxx", (prevState, newState, rule, snapshotValue) -> {
			System.out.println(prevState);
			System.out.println(newState);
			System.out.println(rule.getResource());
			System.out.println(snapshotValue);
		});

		// 创建一个资源名称nodeA的Entry
		for(int i=0; i<10; i++) {
			Entry nodeA = SphU.entry(resourceName);
			if (nodeA != null) {
				try {
					Thread.sleep(20);
					Integer a = null;
					a.intValue();
				} catch (Exception e) {
					// 若需要配置降级规则，需要通过这种方式记录业务异常
					Tracer.trace(e);
				}finally {
					nodeA.exit();
				}
			}
		}

		// 清除上下文
		ContextUtil.exit();
	}

	private static void initDegradeRule(String resourceName) {
	    List<DegradeRule> rules = new ArrayList<>();
	    DegradeRule rule = new DegradeRule();
	    rule.setResource(resourceName);
	    // set threshold RT, 10 ms
	    rule.setCount(10);
	    rule.setStatIntervalMs(60 * 60 * 1000); // 统计1h内的
	    rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
	    rule.setSlowRatioThreshold(0.8);
	    rule.setTimeWindow(1); // 断路器打开时恢复超时(秒)。超时后，断路器将转换为半开状态，以尝试几个请求。
	    rules.add(rule);
	    DegradeRule rule2 = new DegradeRule();
	    rule2.setResource(resourceName);
	    rule2.setCount(15);
	    rule2.setStatIntervalMs(60 * 60 * 2000); // 统计1h内的
	    rule2.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
	    rule2.setTimeWindow(2); // 断路器打开时恢复超时(秒)。超时后，断路器将转换为半开状态，以尝试几个请求。
	    rules.add(rule2);
	    // 加载降级规则
	    DegradeRuleManager.loadRules(rules);
	}

}
